package com.gscitysfy.cus.drain.modules.duty.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gscitysfy.cloudfrmwk.data.mybatis.HerodotusIdentifierGenerator;

import com.gscitysfy.cus.drain.config.BusinessException;
import com.gscitysfy.cus.drain.domain.DutyPlanResult;
import com.gscitysfy.cus.drain.modules.common.enums.NoticeType;
import com.gscitysfy.cus.drain.modules.common.service.SendNoticeService;
import com.gscitysfy.cus.drain.modules.duty.entity.*;
import com.gscitysfy.cus.drain.modules.duty.mapper.MoperDutyHolidayMapper;
import com.gscitysfy.cus.drain.modules.duty.service.*;
import com.gscitysfy.cus.drain.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 钱小龙
 * @version 1.0.0
 * @ClassName MoperDutyHolidayServiceImpl
 * @Description 值班节假日管理
 * @creatTime 2022-03-31 16:47:17
 */
@Slf4j
@Service
public class MoperDutyHolidayServiceImpl extends ServiceImpl<MoperDutyHolidayMapper, MoperDutyEtHoliday> implements MoperDutyHolidayService {

    @Resource
    private MoperDutyHolidayMapper moperDutyHolidayMapper;

    @Resource
    private HerodotusIdentifierGenerator herodotusIdentifierGenerator;

    @Autowired
    private IMoperDutyMnRotaService moperDutyMnRotaService;
    @Autowired
    private IMoperDutyMnClassesService moperDutyMnClassesService;
    @Autowired
    private IMoperDutyMnRuleService moperDutyMnRuleService;
    @Autowired
    private IMoperDutyMnPeopleService moperDutyMnPeopleService;
    @Autowired
    private IMoperDutyRlRecordService moperDutyRlRecordService;
    @Autowired
    private SendNoticeService noticeService;

    private final static String COMMON_CLASS_TYPE = "dutyType1";
    /**
     * 日历导入
     *
     * @param file
     * @return
     * @throws IOException
     */
    @Override
    public List<MoperDutyEtHoliday> importHoliday(MultipartFile file) throws IOException {
        InputStream inputStream = file.getInputStream();
        ExcelReader reader = ExcelUtil.getReader(inputStream);
        List<List<Object>> dataList = reader.read();
        List<MoperDutyEtHoliday> holidayList = new ArrayList<>();
        for (int index = 1; index < dataList.size(); index++) {
            List<Object> row = dataList.get(index);
            MoperDutyEtHoliday moperDutyEtHoliday = new MoperDutyEtHoliday();
            String holidayStr = "";
            if (row.size() > 0 && !Objects.isNull(row.get(0))) {
                //从excel中读取日期和节假日标识放入实体对象中
                holidayStr = row.get(0).toString().substring(0, 4) + "-" + row.get(0).toString().substring(4, 6) + "-" + row.get(0).toString().substring(6, 8);
                moperDutyEtHoliday.setCoamWorkdayFlag(Integer.valueOf(row.get(1).toString()));
                try {
                    Date date = new SimpleDateFormat("yyyy-MM-dd").parse(holidayStr);
                    moperDutyEtHoliday.setCoamHoliday(date);
                } catch (ParseException p) {
                    p.printStackTrace();
                }
            }
            //设置主键
            moperDutyEtHoliday.setCoamKid(herodotusIdentifierGenerator.nextId(moperDutyEtHoliday).toString());
            //根据日期查询是否已存在当天记录，如无则插入，否则更新
            if(StringUtils.isNotEmpty(holidayStr)){
                MoperDutyEtHoliday existHoliday = moperDutyHolidayMapper.selectDutyHoliday(holidayStr);
                if (existHoliday != null) {
                    moperDutyHolidayMapper.updateHoliday(moperDutyEtHoliday, holidayStr);
                } else {
                    moperDutyHolidayMapper.insert(moperDutyEtHoliday);
                }
            }
            holidayList.add(moperDutyEtHoliday);
        }
        return holidayList;
    }


    /**
     * 修改工作日，非工作日
     *
     * @param moperDutyEtHoliday
     * @param
     * @return
     */
    @Override
    public int saveHoliday(MoperDutyEtHoliday moperDutyEtHoliday) throws ParseException {
        //查询前端传来的日期是否存在
        MoperDutyEtHoliday moperDutyEtHoliday1 = moperDutyHolidayMapper.selectDutyHoliday(moperDutyEtHoliday.getCoamHolidayExcel());

        moperDutyEtHoliday.setCoamHoliday(new SimpleDateFormat("yyyy-MM-dd").parse(moperDutyEtHoliday.getCoamHolidayExcel()));
        //如果前端传来的日期不为空就修改工作日状态
        if (moperDutyEtHoliday1 != null) {
            String holiday = new SimpleDateFormat("yyyy-MM-dd").format(moperDutyEtHoliday.getCoamHoliday());
            return moperDutyHolidayMapper.updateHoliday(moperDutyEtHoliday, holiday);
        } else {
            //如果前端传来的日期为空就保存这条数据
            return moperDutyHolidayMapper.insert(moperDutyEtHoliday);
        }
    }


    /**
     * 查询工作日，非工作日
     *
     * @param page
     * @param coamHoliday
     * @param coamWorkdayFlag
     * @return
     */
    @Override
    public IPage<Map<String, Object>> getHoliday(Page<Map<String, Object>> page, String coamHoliday, String coamWorkdayFlag) {
        return moperDutyHolidayMapper.getHoliday(page, coamHoliday, coamWorkdayFlag);
    }


    /**
     * 自动排班
     *
     * @param
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<String> saveAutoDutyPlan(String month, String year) {
        Date planDate;
        //参数不为空，获取参数内的年月
        if (StringUtils.isNotBlank(month) && StringUtils.isNotBlank(year)) {
            planDate = DateUtil.getBeginDate(Integer.parseInt(year), Integer.parseInt(month));
        } else {
            //获取下一个月
            planDate = DateUtil.getNextMonthBeginDate();
        }

        //清除排班信息*/
        moperDutyMnRotaService.removeAllCurrentMonthGenerateDate(planDate);

        //清楚自动排班记录
        moperDutyRlRecordService.removeAllCurrentMonthDutyDate(planDate);

        //获取所有生效的班次信息
        List<MoperDutyMnClasses> list = moperDutyMnClassesService.selectByEnableClassesStatu();
        Assert.notEmpty(list, "当前无可用班次，请先设置值班班次！");
        Map<String, List<MoperDutyMnClasses>> classesMap = this.classesListGroupByDutyType(list);

        //获取当前生效的排班规则
        List<MoperDutyMnRule> listMoperDutyMnRule = moperDutyMnRuleService.getDutyRule();
        Assert.notNull(listMoperDutyMnRule, "当前无可用排班规则，请先设置排班规则！");
        Map<String, MoperDutyMnRule> ruleMap = this.ruleListGroupByDutyType(listMoperDutyMnRule);

        //获取所有自动排班并启用的值班人员
        List<MoperDutyMnPeople> listMoperDutyMnPeople = moperDutyMnPeopleService.selectEnableAutoDutyPeople();
        Assert.notEmpty(listMoperDutyMnPeople, "当前无可用值班人员，请先设置值班人员！");
        Map<String, List<MoperDutyMnPeople>> peopleMap = this.peopleListGroupByDutyType(listMoperDutyMnPeople);
        //排班规则首要判断，假设值班员总人数Y,启用的值班员班次X,满足Y=n（X+1），同时各班次人数为n，
        //满足以上条件可以进行自动排班，否则提示：当前配置人员不足或者班次数过多，请重新配置后自动排班！
        //筛选出值班员总人数
        if (CollectionUtil.isNotEmpty(listMoperDutyMnPeople) && CollectionUtil.isNotEmpty(list)){
            int peopleSize = listMoperDutyMnPeople.stream().
                    filter(people -> COMMON_CLASS_TYPE.equals(people.getCoamPersonType()))
                    .collect(Collectors.toList()).size();
            List<MoperDutyMnClasses> lsClass = list.stream().
                    filter(classes -> COMMON_CLASS_TYPE.equals(classes.getCoamClassessType()))
                    .collect(Collectors.toList());
            if(peopleSize != (lsClass.size() + 1) * (lsClass.get(0).getCoamDutyNum().intValue())){
                throw new BusinessException("当前配置人员不足或者班次数过多，请重新配置后自动排班！");
            }
            //判断值班员班次人数是否一致
            if(CollectionUtil.isNotEmpty(lsClass)){
                Long dutyNum = lsClass.get(0).getCoamDutyNum();
                for (MoperDutyMnClasses classes :lsClass){
                    if (!dutyNum.equals(classes.getCoamDutyNum())){
                        throw new BusinessException("值班员班次人数需保持一致");
                    }
                }
            }
        }else{
            throw new BusinessException("当前配置人员或者班次为空，请重新配置后自动排班！");
        }

        //获取上个月自动排班记录
        List<MoperDutyRlRecord> listRecord = moperDutyRlRecordService.listLastMonthDutyRecord(planDate);
        Map<String, MoperDutyRlRecord> recordMap = this.recordsListGroupByType(listRecord);

        //获取值班月的节假日
        String dutyMonth = DateUtil.formatDate(planDate, "yyyy-MM");
        List<MoperDutyEtHoliday> holidayList = moperDutyHolidayMapper.sel(dutyMonth);

        DutyPlanResult dutyPlanResult = this.generateDutyPlanListByRuleAndClassesInfo(
                classesMap, ruleMap, peopleMap, recordMap, planDate, holidayList);

        //保存信息
        moperDutyRlRecordService.saveBatch(dutyPlanResult.getRecordList());
        moperDutyMnRotaService.saveBatch(dutyPlanResult.getRotaList());
        //向所有参与值排班人员发送通知短信
        List<String> lsDutyPerson = new ArrayList<>();
        listMoperDutyMnPeople.forEach(people -> lsDutyPerson.add(people.getCoamPersonId()));
        return lsDutyPerson;
    }

    @Async("taskPoolExecutor")
    @Override
    public void sendSms(List<String> lsDutyPerson,String message){
        long start = System.currentTimeMillis();
        log.info("开始发送值班短信");
//        noticeService.sendNotice(lsDutyPerson, message, NoticeType.SMS);
        log.info(String.format("值班短信发送结束，耗时%s毫秒", System.currentTimeMillis() - start));
    }

    /**
     * 获取不同值班人员的规则信息
     *
     * @param ruleList
     * @return
     */
    private Map<String, MoperDutyMnRule> ruleListGroupByDutyType(List<MoperDutyMnRule> ruleList) {
        Map<String, MoperDutyMnRule> res = new HashMap<>();
        for (MoperDutyMnRule rule : ruleList) {
            res.put(rule.getCoamDutyPersonType(), rule);
        }
        return res;
    }


    /**
     * 获取不同类型的值班人员
     *
     * @param peopleList
     * @return
     */
    private Map<String, List<MoperDutyMnPeople>> peopleListGroupByDutyType(List<MoperDutyMnPeople> peopleList) {
        if (CollectionUtils.isEmpty(peopleList)) {
            throw new IllegalArgumentException("当前无可用值班人员，请先设置值班人员！");
        }
        return peopleList.stream().collect(Collectors.groupingBy(MoperDutyMnPeople::getCoamPersonType));
    }


    /**
     * 根据班次规则信息生成值班人员列表
     *
     * @param classesMap  班次信息（已按照要求值班人员类型进行了分组）
     * @param ruleMap     值班规则信息（已按照要求值班人员类型进行了分组）
     * @param peopleMap   排班人员信息（已按照要求值班人员类型进行了分组）
     * @param recordMap   上个月值班信息记录（已按照要求值班人员类型进行了分组）
     * @param planDate    指定月份
     * @param holidayList 当月日历配置信息（休息日/工作日）
     * @return
     */
    private DutyPlanResult generateDutyPlanListByRuleAndClassesInfo(
            Map<String, List<MoperDutyMnClasses>> classesMap,
            Map<String, MoperDutyMnRule> ruleMap,
            Map<String, List<MoperDutyMnPeople>> peopleMap,
            Map<String, MoperDutyRlRecord> recordMap,
            Date planDate, List<MoperDutyEtHoliday> holidayList) {
        DutyPlanResult dutyPlanResult = new DutyPlanResult();

        //这里只会循环2次，分别是值班员循环和值班长循环
        for (String key : classesMap.keySet()) {
            List<MoperDutyMnClasses> classesList = classesMap.get(key);
            MoperDutyMnRule rule = ruleMap.get(key);
            List<MoperDutyMnPeople> people = peopleMap.get(key);

            if (CollectionUtils.isEmpty(classesList)) {
            }
            if (rule == null) {
            }
            if (CollectionUtils.isEmpty(people)) {
            }
//            对指定值班人员类型（值班员/值班长）的班次进行排班
            DutyPlanResult planResult = this.generatePersonDutyPlan(
                    classesList, people, rule, recordMap.get(key), planDate, holidayList
            );

            dutyPlanResult.addAllRotaList(planResult.getRotaList());
            dutyPlanResult.addAllRecordList(planResult.getRecordList());

        }
        return dutyPlanResult;
    }


    /**
     * 根据人员类型分组获取上个月末的值班信息
     *
     * @param recordsList
     * @return
     */
    private Map<String, MoperDutyRlRecord> recordsListGroupByType(List<MoperDutyRlRecord> recordsList) {
        Map<String, MoperDutyRlRecord> res = new HashMap<>();
        for (MoperDutyRlRecord record : recordsList) {
            if (res.keySet().contains(record.getCoamPersonType())) {

            } else {
                res.put(record.getCoamPersonType(), record);
            }
        }
        return res;
    }

    /**
     * 生成指定的月份值班工程师值班信息
     *
     * @param classesList 班次信息
     * @param peopleList  值班规则信息
     * @param rule        排班人员信息
     * @param record      上个月值班信息记录 可能未空
     * @param planDate    当月时间
     * @param holidayList 当月日历配置信息（休息日/工作日）
     */
    private DutyPlanResult generatePersonDutyPlan(
            List<MoperDutyMnClasses> classesList,
            List<MoperDutyMnPeople> peopleList,
            MoperDutyMnRule rule,
            MoperDutyRlRecord record,
            Date planDate,
            List<MoperDutyEtHoliday> holidayList) {
        Assert.notEmpty(classesList, "当前无可用班次，请先设置值班班次！");
        Assert.notEmpty(peopleList, "当前无可用值班人员，请先设置值班人员！");
        Assert.notNull(rule, "当前无可用排班规则，请先设置排班规则！");

        //根据排班规则中设置的排班方式（值班人员编号顺序/随机顺序）
        if (rule.getCoamDutyOrder() == 0 && rule.getCoamDutyOrder() != null) {
            //按照人员编号来排序(正序)
            peopleList.sort(Comparator.comparing(MoperDutyMnPeople::getCoamPersonOrder));
        } else {
            //随机排序
            Collections.shuffle(peopleList);
        }

        //循环次数
        Integer cycleTime;
        //值班人员列表下标
        Integer pos;

        //重新开始,随机排序,上个月末记录为空，循环天数改变(重新开始)
        if (rule.getCoamStartPoint() == 1
                || rule.getCoamDutyOrder() == 1
                || record == null
                || !Objects.equals(rule.getCoamCycleDay(), record.getCoamCycleDay())) {

            cycleTime = 0;
            pos = 0;
        } else {
            //值班人员编号
            Integer personOrder;
            //循环模式没有改变,并且上个月的循环模式没有结束
            if (!Objects.equals(record.getCoamCycleDay(), record.getCoamCycleTime())) {
                cycleTime = Math.toIntExact(record.getCoamCycleTime());
                personOrder = Math.toIntExact(record.getCoamPersonMinOrder());
            } else {
                //循环结束
                cycleTime = 0;
                personOrder = Math.toIntExact(record.getCoamPersonMaxOrder() + 1);
            }
            //通过递归和二分查找，找寻指定值班人员编号的编号，找不到就找下一个存在的人员编号
            pos = this.searchPeopleListPosByOrder(peopleList, personOrder);
        }

        return this.generateDutyPlan(pos, cycleTime, peopleList, classesList, rule, planDate, holidayList);
    }


    /**
     * 获取不同类型值班人员的班次信息
     *
     * @param classesList
     * @return
     */
    private Map<String, List<MoperDutyMnClasses>> classesListGroupByDutyType(List<MoperDutyMnClasses> classesList) {
        Map<String, List<MoperDutyMnClasses>> groupMap = classesList.stream().collect(Collectors.groupingBy(MoperDutyMnClasses::getCoamClassessType));
        //对于班次排序
        for (String str : groupMap.keySet()) {
            groupMap.get(str).sort(Comparator.comparingInt(o -> Integer.parseInt(o.getCoamClassessCode().replace("classes", ""))));
        }
        return groupMap;
    }


    /**
     * 根据月份生成对应的值班信息集合
     *
     * @param startPos    循环人员列表起点下标
     * @param cycleTime   已循环次数 （没循环传0）
     * @param peopleList  人员信息列表
     * @param classesList 班次信息列表
     * @param rule        规则信息
     * @param planDate    日历信息
     * @param holidayList 节假日信息列表
     * @return
     */
    private DutyPlanResult generateDutyPlan(
            Integer startPos,
            Integer cycleTime,
            List<MoperDutyMnPeople> peopleList,
            List<MoperDutyMnClasses> classesList,
            MoperDutyMnRule rule,
            Date planDate,
            List<MoperDutyEtHoliday> holidayList) {

        List<MoperDutyMnRota> rotaList = new ArrayList<>();
        MoperDutyRlRecord record = new MoperDutyRlRecord();
        //当月最大天数（例如：1月为 31天，4月为 30天）
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(planDate);
        int maxDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);

        //需要达到的循环天数(值班人员在指定的循环天数内循环使用，到下个循环重新开始)
        int cycleDay = Math.toIntExact((rule.getCoamCycleDay()));
        //值班长循环天数固定为1
        String dutyLeader = "dutyType2";
        if(StringUtils.equals(dutyLeader,rule.getCoamDutyPersonType())){
            cycleDay = 1;
        }

        //当前循环天数
        int currentCycleTime = cycleTime;

        //当月所需值班人员总人数
        int dayOfDutyCount = 0;
        //当前循环周期内下标
        int currentIndex = 0;
        //当天最后一班次开始人员序号
        int cycleLastPerson = 0;
        //循环每天
        for (int day = 1; day <= maxDay; day++) {
            calendar.set(Calendar.DAY_OF_MONTH, day);

            currentCycleTime++;
            //班次循环次数
            int classCycleTime = 0;
            //循环班次
            for (MoperDutyMnClasses classes : classesList) {
                //判断出需要排班的班次
                if (this.isNeedScheduleDuty(classes, rule, calendar, holidayList)) {

                    //班次需要的人数
                    for (int i = 0; i < classes.getCoamDutyNum(); i++) {
//                        新建排班记录
                        MoperDutyMnRota platBasRota = new MoperDutyMnRota();

                        platBasRota.setCoamGenerateDate(calendar.getTime());
                        platBasRota.setCoamClassesId(classes.getCoamKid());
                        platBasRota.setCoamClassesStartTime(DateUtil.parseLocalDateTimeByHourMinute(classes.getCoamClassessStartTime()));
                        platBasRota.setCoamClassesEndTime(DateUtil.parseLocalDateTimeByHourMinute(classes.getCoamClassessEndTime()));

                        platBasRota.setCoamUsable((long) 0);

//                        当天合计下标增长值
                        int planCountIndex = startPos + dayOfDutyCount + i;

                        //当前使用的值班人员下标
                        int peopleIndex = planCountIndex % peopleList.size();

                        MoperDutyMnPeople people = peopleList.get(peopleIndex);

                        platBasRota.setCoamDutyPersonId((people.getCoamPersonId()));
                        platBasRota.setPersonOrder(Math.toIntExact(people.getCoamPersonOrder()));
                        platBasRota.setCoamAddtime(new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
                        rotaList.add(platBasRota);
                        //获取当天第一班开始人员序号
                        if (i == 0 && classCycleTime == 0){
                            cycleLastPerson = platBasRota.getPersonOrder();
                        }
                    }

                    dayOfDutyCount += classes.getCoamDutyNum();
                }
                classCycleTime++;
            }
            //同一循环周期内排班人员相同
            if (currentCycleTime % cycleDay != 0) {
                dayOfDutyCount = currentIndex;
            }else{
                currentIndex = dayOfDutyCount;
            }

        }

        //当月排班结束，记录自动排班记录
        record.setCoamDutyDate(planDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        record.setCoamAddtime(new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        record.setCoamCycleTime((long) currentCycleTime % cycleDay);
        record.setCoamCycleDay((long) cycleDay);
        record.setCoamPersonType(rule.getCoamDutyPersonType());

        Long coamPersonMinOrder = this.compareListToMinOrder(rotaList);
        Long coamPersonMaxOrder = this.compareListToMaxOrder(rotaList);

        //取最小的顺序得员工
        //排序规则为接上月时，记录下月循环开始的人员序号
        if (rule.getCoamStartPoint() == 0L) {
            //当月循环已结束，下月排班开始于本月最后值班人下一位，否则从最后一天首班开始人员继续循环
            if (record.getCoamCycleTime() == 0){
                Long lastPersonOrder = rotaList.get(rotaList.size()-1).getPersonOrder().longValue() + 1L;
                coamPersonMinOrder = lastPersonOrder >= coamPersonMaxOrder ? 1L :lastPersonOrder;
            }else{
                coamPersonMinOrder = (long)cycleLastPerson;
            }
        }
        record.setCoamPersonMinOrder(coamPersonMinOrder);
        //取最大的顺序得员工
        record.setCoamPersonMaxOrder(coamPersonMaxOrder);

        //组装返回结果
        DutyPlanResult planResult = new DutyPlanResult();
        planResult.addAllRotaList(rotaList);
        planResult.addAllRecordList(Collections.singletonList(record));
        return planResult;
    }

    /**
     * 取最大的顺序得员工
     *
     * @param rotaList
     * @return
     */
    private Long compareListToMaxOrder(List<MoperDutyMnRota> rotaList) {
        MoperDutyMnRota moperDutyMnRota = rotaList.stream().max(Comparator.comparingInt(MoperDutyMnRota::getPersonOrder)).get();
        return moperDutyMnRota.getPersonOrder().longValue();
    }

    /**
     * 取最小的顺序得员工
     *
     * @param rotaList
     * @return
     */
    private Long compareListToMinOrder(List<MoperDutyMnRota> rotaList) {
        MoperDutyMnRota moperDutyMnRota = rotaList.stream().min(Comparator.comparingInt(MoperDutyMnRota::getPersonOrder)).get();
        return moperDutyMnRota.getPersonOrder().longValue();
    }


    /**
     * 判断当前的班次是否需要排班
     *
     * @param classes     班次
     * @param rule        排班规则
     * @param calendar    当前时间
     * @param holidayList 节假日日历
     * @return true 排班 false 不排班
     */
    private Boolean isNeedScheduleDuty(MoperDutyMnClasses classes, MoperDutyMnRule rule, Calendar calendar, List<MoperDutyEtHoliday> holidayList) {
        //如果班次要求的值班人员类型和 自动排班规则中要求的值班人员类型不一致就不处理
        if (!StringUtils.equals(classes.getCoamClassessType(), rule.getCoamDutyPersonType())) {
            throw new IllegalArgumentException("班次要求的值班人员类型和 自动排班规则中要求的值班人员类型不一致");
        }
        ///值班长不再区分是否工作日且只存在一个值班班次
        //只值班长才会区分工作日和非工作日排班
        //* dutyType1：值班员
        //* dutyType2：值班长
        /*
        if (StringUtils.equals("dutyType2", rule.getCoamDutyPersonType())) {
            //区分工作日/非工作日
            if (rule.getCoamIsWorkDay() != null && rule.getCoamIsWorkDay() == 0) {
                //查看当天是否属于工作日
                if (isWorkDay(calendar, holidayList)) {
                    //工作日值班班次配置中，是否包含当前班次，包含则排班，不包含不排班
                    return rule.getCoamWorkClasses().contains(classes.getCoamKid());
                } else {
                    //非工作日值班班次配置
                    return rule.getCoamWeekendClasses().contains(classes.getCoamKid());
                }

            }
        }*/

        return true;
    }


    /**
     * 判断当前是否属于工作日
     *
     * @param calendar
     * @param holidayList
     * @return true 工作日 false 非工作日
     */
    private Boolean isWorkDay(Calendar calendar, List<MoperDutyEtHoliday> holidayList) {
        //优先判断是否节假日列表设定的工作日
        for (MoperDutyEtHoliday holiday : holidayList) {
            if (StringUtils.equals(
                    DateUtil.formatDate(holiday.getCoamHoliday(), "yyyy-MM-dd"),
                    DateUtil.formatDate(calendar.getTime(), "yyyy-MM-dd")
            )) {
                return holiday.getCoamWorkdayFlag() == 0;
            }
        }
        //不在节假日列表再判断是否双休日
        if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY
                || calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
            return false;
        }
        return true;
    }


    /**
     * 根据人员编号获取所在人员列表里面的排序下标,如果这个编号不存在，则找下一位
     *
     * @param peopleList  人员列表
     * @param personOrder 人员编号
     * @return 返回下标值
     */
    private Integer searchPeopleListPosByOrder(List<MoperDutyMnPeople> peopleList, Integer personOrder) {
        int start = 0;
        int end = peopleList.size() - 1;
        if (personOrder > peopleList.get(end).getCoamPersonOrder()) {
            return 0;
        }
        while (start <= end) {
            int mid = (start + end) / 2;
            Integer midPeopleOrder = peopleList.get(mid).getCoamPersonOrder();
            if (midPeopleOrder.equals(personOrder)) {
                return mid;
            }
            if (midPeopleOrder < personOrder) {
                start = mid + 1;
            }
            if (midPeopleOrder > personOrder) {
                end = mid - 1;
            }
        }
        return searchPeopleListPosByOrder(peopleList, personOrder + 1);
    }



}

